﻿using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

namespace ZOIL.Framework.Core
{
	#region Abstract Converter Implementation

	/// <summary>
	/// An abstract value converter that is implemented as a markup extension so it can be used more easily in xaml
	/// See http://www.codeproject.com/Articles/69528/Quick-WPF-tip-Generic-Converter-MarkupExtension.aspx for details
	/// </summary>
	/// <typeparam name="T"></typeparam>
	[MarkupExtensionReturnType(typeof(IValueConverter))]
	public abstract class ConverterMarkupExtension<T> : MarkupExtension where T : class, IValueConverter, new()
	{
		private static T _converter;

        /// <inheritdoc/>
        public override object ProvideValue(IServiceProvider serviceProvider)
		{
			if (_converter == null)
			{
				_converter = new T();
			}
			return _converter;
		}
	}
	
	#endregion

	#region Visibility Converter

	/// <summary>
	/// A value converter that converts a boolean value to a visibility value (true: Visible, false: Collapsed)
	/// </summary>
	public class BooleanToVisibilityConverter : ConverterMarkupExtension<BooleanToVisibilityConverter>, IValueConverter
	{
        /// <inheritdoc/>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			if (value != null)
			{
				bool state = (bool)value;

				if (state)
					return Visibility.Visible;
				else
					return Visibility.Collapsed;
			}
			return Visibility.Collapsed;
		}

        /// <inheritdoc/>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
            throw new NotImplementedException();
		}
    }

	#endregion

    #region BooleanNotConverter

    /// <summary>
    /// A value Converter that inverts a boolean value by applying the boolean NOT operation
    /// </summary>
    public class BooleanNotConverter : ConverterMarkupExtension<BooleanNotConverter>, IValueConverter
    {
        /// <inheritdoc/>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null)
            {
                bool state = (bool)value;

                return !state;
            }
            return value;
        }

        /// <inheritdoc/>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Convert(value, targetType, parameter, culture);
        }
    }

    #endregion

    #region Dummy Converter

    /// <summary>
	/// A value converter that is solely used for debugging purposes
	/// </summary>
	public class DummyConverter : ConverterMarkupExtension<DummyConverter>, IValueConverter
	{
        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
		public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			return value;
		}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
		public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
		{
			return value;
		}
	}

	#endregion
}
